#pragma once
#include "Thread.hpp"
#include "LockGuard.hpp"
#include "Task.hpp"
#include <queue>
#include <vector>
using namespace liang;

// 声明
template <class T>
class Threadpool;

template <class T>
struct ThreadData
{
    Threadpool<T> *_tp;
    string _threadname;
    ThreadData(Threadpool<T> *tp, string name)
        : _tp(tp), _threadname(name)
    {
    }
};

static int g_num = 3; // 内部设定好线程的个数

template <class T>
class Threadpool
{
private:
    static void *handler_task(void *args)
    {
        ThreadData<T> *td = static_cast<ThreadData<T> *>(args);
        while (true)
        {
            T t;
            {
                LockGuard lg(td->_tp->getmutex());
                // 从队列中拿任务
                while (td->_tp->IsQueueEmpty())
                {
                    // 没有任务就等待
                    td->_tp->pthreadWait();
                }
                t = td->_tp->pop();
            }
            //在外面执行任务，这样可以提高效率
            // 执行对应的任务
            cout << "thread " << td->_threadname << "接受了任务：" << t.ToString() << " 并完成任务:" << t() << endl;
        }
    }
    Threadpool(const Threadpool<T>*) = delete;
    void operator=(const Threadpool<T>*) = delete;

    Threadpool(const int num = g_num)
        : _num(num)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
        // 创建线程
        for (int i = 0; i < _num; ++i)
        {
            _threads.push_back(new Thread());
        }
    }

public:
    //设计成单例模式
    static Threadpool<T>* GetInstance()
    {
        //双检查
        if(_tp == nullptr)
        {
            LockGuard lg(&_singlelock);
            if(_tp == nullptr)
            {
                _tp = new Threadpool<T>();
            }
        }
        return _tp;
    }

    void pthreadWait()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }
    pthread_mutex_t *getmutex()
    {
        return &_mutex;
    }
    bool IsQueueEmpty()
    {
        return _task_queue.empty();
    }
    T pop()
    {
        T t = _task_queue.front();
        _task_queue.pop();
        return t;
    }

public:
    // 运行
    void run()
    {
        for (auto &t : _threads)
        {
            // 拿到线程的相关信息，然后执行
            ThreadData<T> *td = new ThreadData<T>(this, t->threadname());
            t->start(handler_task, td);
            cout << "thread " << t->threadname() << " runing " << endl;
        }
    }
    // 往任务队列中放入任务
    void push(const T &in)
    {
        LockGuard lg(&_mutex);
        _task_queue.push(in);
        // 通知线程执行任务
        pthread_cond_signal(&_cond);
    }
    ~Threadpool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        for (auto &t : _threads)
        {
            delete t;
        }
    }

private:
    queue<T> _task_queue;      // 任务队列
    int _num;                  // 线程的数量
    vector<Thread *> _threads; // 用来存储线程信息
    pthread_mutex_t _mutex;
    pthread_cond_t _cond; // 条件变量

    static Threadpool<T>* _tp; //懒汉模式
    static pthread_mutex_t _singlelock;
};


template <class T>
Threadpool<T>* Threadpool<T>::_tp = nullptr;

template <class T>
pthread_mutex_t Threadpool<T>::_singlelock;      